package main

import (
	"fmt"
	"time"
)

func main() {
	//noBufferChannel()
	//bufferChannel()
	//forRangeChannel()

	//readOnlyAndWriteOnlyChannel()

	channelListener()
}

// 无缓冲管道
// 必须让接收方先启动否则会死锁
func noBufferChannel() {
	//定义管道
	countChannel := make(chan int)
	go func() {
		for i := 0; i < 50; i++ {
			childCount := <-countChannel //子读数据
			fmt.Println("子go程死循环。。。。。", childCount)
		}
	}()
	//主go程

	for i := 0; i < 50; i++ {

		countChannel <- i //向管道写入数据
		time.Sleep(1 * time.Second)
	}

	time.Sleep(5 * time.Second)
}

/*有缓冲区的管道*/
func bufferChannel() {
	countChannel := make(chan int, 10)
	go func() {
		for i := 0; i < 50; i++ {
			fmt.Println("读中.....", <-countChannel)
		}
	}()

	for i := 0; i < 50; i++ {
		countChannel <- i
		fmt.Println("写中.....")
	}
}

// for range解决读写次数不一致问题
func forRangeChannel() {
	chann := make(chan int, 100)

	go func() {
		for {
			//判断管道是否被关闭
			v, ok := <-chann
			fmt.Println("v", v, "ok", ok) //没关闭会返回true，关闭则会返回false
			if !ok {
				break
			}
		}
	}()
	go func() {
		for i := 0; i < 100; i++ {
			chann <- i
			fmt.Println("写入数据中....", i)
		}
		close(chann)
	}()

	for v := range chann {
		fmt.Println("读数据", v)
	}

}

func readOnlyAndWriteOnlyChannel() {
	channel := make(chan int, 100)

	go writeOnly(channel)

	go readOnly(channel)

	time.Sleep(10 * time.Second)
}

// 只读通道
func readOnly(readOnlyChannel <-chan int) {
	for v := range readOnlyChannel {
		fmt.Println("只读通道读数据中....", v)
	}
}

// 只写通道
func writeOnly(writeOnly chan<- int) {
	for i := 0; i < 100; i++ {
		writeOnly <- i
		fmt.Println("只写通道写数据中", i)
	}
}

// select监听管道
func channelListener() {
	oneChannel := make(chan int)

	twoChannel := make(chan int)

	go func() {
	OuterLoop:
		for {
			select {
			case data := <-oneChannel:
				fmt.Println("one channel listener", data)
				break OuterLoop
			case data := <-twoChannel:
				fmt.Println("tow channel listener", data)
			}
		}
	}()

	go func() {
		for i := 0; i < 100; i++ {
			oneChannel <- i
			fmt.Println("one channel writing....", i)
		}
	}()

	go func() {
		for i := 0; i < 100; i++ {
			twoChannel <- i
			fmt.Println("two channel writing", i)
		}
	}()

	time.Sleep(10 * time.Second)
}
